/*
*****************************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2002-2012, Advanced Audio Video Coding Standard, Part II
*
* DISCLAIMER OF WARRANTY
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations under
* the License.
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
* The AVS Working Group doesn't represent or warrant that the programs
* furnished here under are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy for standardization procedure is available at
* AVS Web site http://www.avs.org.cn. Patent Licensing is outside
* of AVS Working Group.
*
* The Initial Developer of the Original Code is Video subgroup of AVS
* Workinggroup.
* Contributors: Qin Yu,         Zhichu He,  Weiran Li,    Yong Ling,
*               Zhenjiang Shao, Jie Chen,   Junjun Si,    Xiaozhen Zheng, 
*               Jian Lou,       Qiang Wang, Jianwen Chen, Haiwu Zhao,
*               Guoping Li,     Siwei Ma,   Junhao Zheng, Zhiming Wang
*               Li Zhang,
******************************************************************************
*/


#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#include "../../lcommon/inc/memalloc.h"
#include "global.h"
#include "../../lcommon/inc/commonVariables.h"
#include "../../lcommon/inc/transform.h"
#include "../../lcommon/inc/defines.h"
#include "vlc.h"
#include "header.h"
#include "AEC.h"  
#include "math.h"
#if ALF
#include "DecAdaptiveLoopFilter.h"
#endif

// Adaptive frequency weighting quantization
#if FREQUENCY_WEIGHTING_QUANTIZATION
#include "wquant.h"
#endif


CameraParamters CameraParameter, *camera = &CameraParameter;

extern StatBits *StatBitsPtr;  

#if MULTIVIEW_CODING
extern multiView_StatBits[MAX_VIEW];
extern multiView_depth_StatBits[MAX_VIEW];
#endif


const int  InterlaceSetting[] = { 4, 4, 0, 5, 0, 5, 0, 5, 3, 3, 3, 3, 0,
                                  0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 4, 0
                                };


/*
*************************************************************************
* Function:sequence header
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void SequenceHeader ( char *buf, int startcodepos, int length )
{
	int i, j;

  memcpy ( currStream->streamBuffer, buf, length );
  currStream->code_len = currStream->bitstream_length = length;
  currStream->read_len = currStream->frame_bitoffset = ( startcodepos + 1 ) * 8;

  input->profile_id           = u_v ( 8, "profile_id" );
  input->level_id             = u_v ( 8, "level_id" );

#if MULTIVIEW_CODING
  input->view_number          = u_v ( 4, "View_number" );
  input->bUseDepth            = u_v ( 1, "bUseDepth" );
#endif

  progressive_sequence        = u_v ( 1, "progressive_sequence" );
#if INTERLACE_CODING
  is_field_sequence           = u_v ( 1, "field_coded_sequence");
#endif
#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
  img->is_field_sequence    = is_field_sequence;
#endif
  horizontal_size             = u_v ( 14, "horizontal_size" );
  vertical_size               = u_v ( 14, "vertical_size" );
  input->chroma_format               = u_v ( 2, "chroma_format" );
#if EXTEND_BD
	input->output_bit_depth = 8;
	input->sample_bit_depth = 8;
  sample_precision            = 1;
  if (input->profile_id == BASELINE10_PROFILE) // 10bit profile (0x52)
  {
		input->output_bit_depth = u_v (3, "sample_precision" );
		input->output_bit_depth = 6 + (input->output_bit_depth) * 2;
		input->sample_bit_depth = u_v (3, "encoding_precision" );
		input->sample_bit_depth = 6 + (input->sample_bit_depth) * 2;
  }
	else // other profile
	{
#endif
		sample_precision            = u_v ( 3, "sample_precision" );
#if EXTEND_BD
	}
#endif
  aspect_ratio_information    = u_v ( 4, "aspect_ratio_information" );
  frame_rate_code             = u_v ( 4, "frame_rate_code" );

  bit_rate_lower              = u_v ( 18, "bit_rate_lower" );
  marker_bit                  = u_v ( 1,  "marker bit" );
  //CHECKMARKERBIT
  bit_rate_upper              = u_v ( 12, "bit_rate_upper" );
  low_delay                   = u_v ( 1, "low_delay" );
  marker_bit                  = u_v ( 1, "marker bit" );
  //CHECKMARKERBIT
#if M3480_TEMPORAL_SCALABLE
  temporal_id_exist_flag      = u_v(1, "temporal_id exist flag");							//get Extention Flag
#endif
  u_v ( 18, "bbv buffer size" );
  input->g_uiMaxSizeInBit     = u_v ( 3, "Largest Coding Block Size" );

#if FREQUENCY_WEIGHTING_QUANTIZATION
  weight_quant_enable_flag		      = u_v ( 1, "weight_quant_enable" );
  if (weight_quant_enable_flag) {
    load_seq_weight_quant_data_flag        = u_v ( 1, "load_seq_weight_quant_data_flag");
    if (load_seq_weight_quant_data_flag) {
      int x,y,sizeId,uiWqMSize;
      for (sizeId=0;sizeId<2;sizeId++)
      {
        uiWqMSize=min(1<<(sizeId+2),8);
        for(y=0; y<uiWqMSize; y++)
        {
          for(x=0; x<uiWqMSize; x++)
          {
            cur_wq_matrix[sizeId][y*uiWqMSize+x]= ue_v("weight_quant_coeff");
          }
        }
      }
    }
  }
#endif

#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
  background_picture_enable = 0x01 ^ u_v(1,"background_picture_disable");
#else
  if(input->profile_id == 0x50)
  {
    background_picture_enable = 0x01 ^ u_v(1,"background_picture_disable");
  }
  else
  {
    background_picture_enable = 0;
  }
#endif
#endif

#if !D20141230_BUG_FIX
#if DMH
  b_dmh_enabled		      = u_v ( 1, "dmh enabled" );
#endif
#else 
#if DMH
  b_dmh_enabled		      = 1;
#endif
#endif 

#if MH_PSKIP_NEW
  b_mhpskip_enabled       = u_v ( 1, "mhpskip enabled");
#endif
#if FFRAME
  dhp_enabled		      = u_v ( 1, "dhp enabled" );
  wsm_enabled		      = u_v ( 1, "wsm enabled" );
#endif

  img->inter_amp_enable       = u_v ( 1, "Asymmetric Motion Partitions" );
  input->useNSQT              = u_v ( 1, "useNSQT" );
  input->useSDIP              =u_v ( 1, "useNSIP" );
  
#if SEC_TRANS
  b_secT_enabled		      = u_v ( 1, "secT enabled" );
#endif

  input->sao_enable = u_v ( 1, "SAO Enable Flag" );
#if ALF
  input->alf_enable = u_v(1,"ALF Enable Flag");
#endif

  b_pmvr_enabled		      = u_v ( 1, "pmvr enabled" );

  gop_size = u_v( 6, "num_of_RPS");
  for ( i=0; i<gop_size; i++)
  {
	  decod_RPS[i].referd_by_others =u_v(1,"refered by others");
	  decod_RPS[i].num_of_ref = u_v( 3, "num of reference picture" );

	  for ( j=0; j<decod_RPS[i].num_of_ref; j++)
	  {
#if REF_CD
		  decod_RPS[i].ref_pic[j]= u_v( 6, "delta COI of ref pic" );
#else
		  decod_RPS[i].ref_pic[j]= u_v( 6, "delta COI of ref pic" ) + 1;
#endif
	  }
	  decod_RPS[i].num_to_remove = u_v( 3, "num of removed picture" );

	  for ( j=0; j<decod_RPS[i].num_to_remove; j++)
	  {
#if REF_CD
		  decod_RPS[i].remove_pic[j] = u_v( 6, "delta COI of removed pic" );
#else
		  decod_RPS[i].remove_pic[j] = u_v( 6, "delta COI of removed pic" )+1;
#endif
	  }
  }
#if PDD
  if (low_delay == 0)
  {
	  picture_reorder_delay =  u_v( 5, "picture_reorder_delay" );
  }
#endif

#if XL_ADDED
  input->crossSliceLoopFilter = u_v(1, "Cross Loop Filter Flag");
#endif

  if ( input->profile_id == RESERVED_PROFILE_ID )
  {
    input->slice_set_enable = /*slice_set_enable =*/ 0x01 ^ u_v ( 1, "slice set flag" );         //added by mz, 2008.04
  }
  else
  {
    u_v ( 3, "reserved bits" );
  }

  img->width          = horizontal_size;
  img->height         = vertical_size;
  img->width_cr       = ( img->width >> 1 );

  if ( input->chroma_format == 1 )
  {
    img->height_cr      = ( img->height >> 1 );
  }

  img->PicWidthInMbs  = img->width / MIN_CU_SIZE;
  img->PicHeightInMbs = img->height / MIN_CU_SIZE;
  img->PicSizeInMbs   = img->PicWidthInMbs * img->PicHeightInMbs;
  img->buf_cycle      = input->buf_cycle + 1;
  img->max_mb_nr      = ( img->width * img->height ) / ( MIN_CU_SIZE * MIN_CU_SIZE );

  seq_header ++;
}


void video_edit_code_data ( char *buf, int startcodepos, int length )
{
  currStream->frame_bitoffset = currStream->read_len = ( startcodepos + 1 ) * 8;
  currStream->code_len = currStream->bitstream_length = length;
  memcpy ( currStream->streamBuffer, buf, length );
  vec_flag = 1;
}
/*
*************************************************************************
* Function:I picture header  //sw
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void I_Picture_Header ( char *buf, int startcodepos, int length )
{
  int i;
  currStream->frame_bitoffset = currStream->read_len = ( startcodepos + 1 ) * 8;
  currStream->code_len = currStream->bitstream_length = length;
  memcpy ( currStream->streamBuffer, buf, length );

  u_v ( 32, "bbv_delay" );

  time_code_flag       = u_v ( 1, "time_code_flag" );

  if ( time_code_flag )
  {
    time_code        = u_v ( 24, "time_code" );
  }

#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
  if(background_picture_enable )
#else
  if(input->profile_id == 0x50 && background_picture_enable )
#endif
  {
	  background_picture_flag = u_v ( 1, "background_picture_flag" );

	  if(background_picture_flag)
		  img->typeb = BACKGROUND_IMG;				
	  else
		  img->typeb = 0;

	  if(img->typeb == BACKGROUND_IMG)
		  background_picture_output_flag = u_v ( 1, "background_picture_output_flag" );  
  }
#endif

  {
    img->coding_order         = u_v ( 8, "coding_order" );
#if M3480_TEMPORAL_SCALABLE
	if ( temporal_id_exist_flag == 1 )
	{
		cur_layer = u_v( TEMPORAL_MAXLEVEL_BIT, "temporal_id" );
	}
#endif
#if PDD
	if (low_delay == 0)
	{
		displaydelay =   ue_v("picture_output_delay");
	}

#else
	delta_COI_POI =  se_v("distance between coding order and play order");
#endif
  }
  {
    int RPS_idx;// = (img->coding_order-1) % gop_size;
    int predict;
    predict = u_v( 1, "use RCS in SPS");
    if (predict)
    {
      RPS_idx = u_v( 5, "predict for RCS");
      curr_RPS = decod_RPS[RPS_idx];
    }
    else
    {
      //gop size16
      int j;
      curr_RPS.referd_by_others =u_v(1,"refered by others");
      curr_RPS.num_of_ref = u_v( 3, "num of reference picture" );
      for ( j=0; j<curr_RPS.num_of_ref; j++)
      {
        curr_RPS.ref_pic[j] = u_v( 6, "delta COI of ref pic");
      }
      curr_RPS.num_to_remove = u_v( 3, "num of removed picture" );
      for ( j=0; j<curr_RPS.num_to_remove; j++)
      {
        curr_RPS.remove_pic[j] = u_v( 6, "delta COI of removed pic" );
      }
    }
  }
  //xyji 12.23
  if ( low_delay )
  {
    ue_v ( "bbv check times" );
  }

  progressive_frame    = u_v ( 1, "progressive_frame" );

  if ( !progressive_frame )
  {
    img->picture_structure   = u_v ( 1, "picture_structure" );
  }
  else
  {
    img->picture_structure = 1;
  }

  top_field_first      = u_v ( 1, "top_field_first" );
  repeat_first_field   = u_v ( 1, "repeat_first_field" );
#if INTERLACE_CODING
  if (is_field_sequence)
  {
    is_top_field         = u_v ( 1, "is_top_field" );
#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
    img->is_top_field       = is_top_field;
#endif
    u_v ( 1, "reserved bit for interlace coding");
  }
#endif
  fixed_picture_qp     = u_v ( 1, "fixed_picture_qp" );
  picture_qp           = u_v ( 7, "picture_qp" );
#if EXTEND_BD
	//picture_qp = picture_qp + (8 * (input->sample_bit_depth - 8));
#endif
 
  loop_filter_disable = u_v ( 1, "loop_filter_disable" );

  if ( !loop_filter_disable )
  {
    loop_filter_parameter_flag = u_v ( 1, "loop_filter_parameter_flag" );

    if ( loop_filter_parameter_flag )
    {
      input->alpha_c_offset = se_v ( "alpha_offset" );
      input->beta_offset  = se_v ( "beta_offset" );
    }
    else  // 20071009
    {
      input->alpha_c_offset = 0;
      input->beta_offset  = 0;
    }
  }

  // Adaptive frequency weighting quantization
#if FREQUENCY_WEIGHTING_QUANTIZATION

  pic_weight_quant_enable_flag=u_v(1,"pic_weight_quant_enable");
  if(weight_quant_enable_flag&&pic_weight_quant_enable_flag)
  {
	  load_pic_weight_quant_data_type=u_v(1,"load_pic_weight_quant_data_type");  //M2331 2008-04
      if (load_pic_weight_quant_data_type == 1)
      {
          int x,y,sizeId,uiWqMSize;
          for (sizeId=0;sizeId<2;sizeId++)
          {
              int i=0;
              uiWqMSize=min(1<<(sizeId+2),8);
              for(y=0; y<uiWqMSize; y++)
              {
                  for(x=0; x<uiWqMSize; x++)
                  {
                      user_wq_matrix[sizeId][i++]= ue_v("weight_quant_coeff");
                  }
              }
          }
      } else {
      mb_adapt_wq_disable=u_v(1,"reserved_bits");  //M2331 2008-04
#if CHROMA_DELTA_QP
	  chroma_quant_param_disable=u_v(1,"chroma_quant_param_disable");
	  if(!chroma_quant_param_disable)
	  {
		  chroma_quant_param_delta_u=se_v("chroma_quant_param_delta_cb");
		  chroma_quant_param_delta_v=se_v("chroma_quant_param_delta_cr");
	  }
#endif
	  weighting_quant_param=u_v(2,"weighting_quant_param_index");

	  weighting_quant_model=u_v(2,"weighting_quant_model");
	  CurrentSceneModel = weighting_quant_model;

	  //M2331 2008-04
	  if(weighting_quant_param==1)
	  {
		  for( i=0;i<6;i++)
			  quant_param_undetail[i]=(char)se_v("quant_param_delta_u")+wq_param_default[UNDETAILED][i];
	  }
	  if(weighting_quant_param==2)
	  {
		  for( i=0;i<6;i++)
			  quant_param_detail[i]=(char)se_v("quant_param_delta_d")+wq_param_default[DETAILED][i];
	  }
	  //M2331 2008-04
    }
  }
#endif

  img->qp                = picture_qp;

  img->type              = I_IMG;

#if MULTIVIEW_CODING
  if(img->view_index == 0)
  {
	  img->baseView_type = img->type;
  }
#endif
}

/*
*************************************************************************
* Function:pb picture header
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void PB_Picture_Header ( char *buf, int startcodepos, int length )
{
  int i;
  currStream->frame_bitoffset = currStream->read_len = ( startcodepos + 1 ) * 8;
  currStream->code_len = currStream->bitstream_length = length;
  memcpy ( currStream->streamBuffer, buf, length );

  u_v ( 32, "bbv delay" );
  
  picture_coding_type       = u_v ( 2, "picture_coding_type" );

#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
  if( background_picture_enable && (picture_coding_type == 1 || picture_coding_type == 3) )
#else
  if( background_picture_enable && picture_coding_type == 1 && input->profile_id == 0x50 )
#endif
  {
#ifdef AVS2_S2_S
#if AVS2_SCENE_CD
	if(picture_coding_type ==1){
#endif
    background_pred_flag      = u_v ( 1, "background_pred_flag" ); 
#if AVS2_SCENE_CD
	}else{
		background_pred_flag = 0;
	}
#endif
    if( background_pred_flag == 0 ) 
    {
#endif
      background_reference_enable = u_v ( 1, "background_reference_enable" );
#ifdef AVS2_S2_S
    }
    else
    {
        background_reference_enable = 0;
    }
#endif
  }
#ifdef AVS2_S2_SBD
  else
  {
    background_pred_flag = 0;
    background_reference_enable = 0;
  }
#endif
#endif

#ifdef AVS2_S2_S
  if(picture_coding_type == 1 && background_pred_flag)
  {
	  img->typeb = BP_IMG;
  }
  else
  {
	  img->typeb = 0;
  }
#endif

  {
	  img->coding_order         = u_v ( 8, "coding_order" );
#if M3480_TEMPORAL_SCALABLE
	  if ( temporal_id_exist_flag == 1 )
		  cur_layer = u_v( TEMPORAL_MAXLEVEL_BIT, "temporal_id" );
#endif

#if PDD
	  if (low_delay == 0)
	  {
		  displaydelay =   ue_v("displaydelay");
	  }
#else
	  delta_COI_POI =  se_v("distance between coding order and play order");
#endif
  }
#if MULTIVIEW_CODING
  if ( picture_coding_type == 1 )
  {
	  img->type = P_IMG;
  }
#if DHP
  else if ( picture_coding_type == 3 )
  {
	  img->type = F_IMG;
  }
#endif
  else
  {
	  img->type = B_IMG;
  }
  if(img->view_index == 0)
  {
	  img->baseView_type = img->type;
  }
  if (img->baseView_type != I_IMG)
#endif
  {
	  int RPS_idx;// = (img->coding_order-1) % gop_size;
	  int predict;
	  predict = u_v( 1, "use RPS in SPS");
	  if (predict)
	  {
		  RPS_idx = u_v( 5, "predict for RPS");
		  curr_RPS = decod_RPS[RPS_idx];
	  }
	  else
	  {
		  //gop size16
		  int j;
		  curr_RPS.referd_by_others =u_v(1,"refered by others");
		  curr_RPS.num_of_ref = u_v( 3, "num of reference picture" );
		  for ( j=0; j<curr_RPS.num_of_ref; j++)
		  {
			  curr_RPS.ref_pic[j] = u_v( 6, "delta COI of ref pic");
		  }
		  curr_RPS.num_to_remove = u_v( 3, "num of removed picture" );
		  for ( j=0; j<curr_RPS.num_to_remove; j++)
		  {
			  curr_RPS.remove_pic[j] = u_v( 6, "delta COI of removed pic" );
		  }
	  }
  }
  //xyji 12.23
  if ( low_delay )
  {
    ue_v ( "bbv check times" );
  }

  progressive_frame        = u_v ( 1, "progressive_frame" );

  if ( !progressive_frame )
  {
    img->picture_structure = u_v ( 1, "picture_structure" );
  }
  else
  {
    img->picture_structure   = 1;
  }

  top_field_first        = u_v ( 1, "top_field_first" );
  repeat_first_field     = u_v ( 1, "repeat_first_field" );
#if INTERLACE_CODING
  if (is_field_sequence)
  {
    is_top_field         = u_v ( 1, "is_top_field" );
#if HALF_PIXEL_COMPENSATION || HALF_PIXEL_CHROMA
    img->is_top_field       = is_top_field;
#endif
    u_v ( 1, "reserved bit for interlace coding");
  }
#endif

  fixed_picture_qp       = u_v ( 1, "fixed_picture_qp" );
  picture_qp             = u_v ( 7, "picture_qp" );
#if EXTEND_BD
	//picture_qp = picture_qp + (8 * (input->sample_bit_depth - 8));
#endif

  if ( ! ( picture_coding_type == 2 && img->picture_structure == 1 ) )
  {
#if !M3595_REMOVE_REFERENCE_FLAG
    picture_reference_flag = u_v ( 1, "picture_reference_flag" );
#else 
    u_v ( 1, "reserved_bit" );
#endif 
  }
#if !M3475_RANDOM_ACCESS
  img->no_forward_reference = u_v ( 1, "no_forward_reference_flag" );
#else 
  img->random_access_decodable_flag = u_v ( 1, "random_access_decodable_flag" );
#endif 
  u_v ( 3, "reserved bits" );

  /*  skip_mode_flag      = u_v(1,"skip_mode_flag");*/  //qyu0822 delete skip_mode_flag
  loop_filter_disable = u_v ( 1, "loop_filter_disable" );

  if ( !loop_filter_disable )
  {
    loop_filter_parameter_flag = u_v ( 1, "loop_filter_parameter_flag" );

    if ( loop_filter_parameter_flag )
    {
      input->alpha_c_offset = se_v ( "alpha_offset" );
      input->beta_offset  = se_v ( "beta_offset" );
    }
    else
    {
      input->alpha_c_offset = 0;
      input->beta_offset  = 0;
    }
  }
  // Adaptive frequency weighting quantization
#if FREQUENCY_WEIGHTING_QUANTIZATION

  pic_weight_quant_enable_flag=u_v(1,"pic_weight_quant_enable");
  if(weight_quant_enable_flag&&pic_weight_quant_enable_flag)
  {
      load_pic_weight_quant_data_type=u_v(1,"load_pic_weight_quant_data_type");  //M2331 2008-04
      if (load_pic_weight_quant_data_type == 1)
      {
          int x,y,sizeId,uiWqMSize;
          for (sizeId=0;sizeId<2;sizeId++)
          {
              int i=0;
              uiWqMSize=min(1<<(sizeId+2),8);
              for(y=0; y<uiWqMSize; y++)
              {
                  for(x=0; x<uiWqMSize; x++)
                  {
                      user_wq_matrix[sizeId][i++]= ue_v("weight_quant_coeff");
                  }
              }
          }
      } else {      
	  mb_adapt_wq_disable=u_v(1,"reserved_bits");  //M2331 2008-04
#if CHROMA_DELTA_QP
	  chroma_quant_param_disable=u_v(1,"chroma_quant_param_disable");
	  if(!chroma_quant_param_disable)
	  {
		  chroma_quant_param_delta_u=se_v("chroma_quant_param_delta_cb");
		  chroma_quant_param_delta_v=se_v("chroma_quant_param_delta_cr");
	  }
#endif
	  weighting_quant_param=u_v(2,"weighting_quant_param_index");

	  weighting_quant_model=u_v(2,"weighting_quant_model");
	  CurrentSceneModel = weighting_quant_model;

	  //M2331 2008-04
	  if(weighting_quant_param==1)
	  {
		  for(i=0;i<6;i++)
			  quant_param_undetail[i]=(char)se_v("quant_param_delta_u")+wq_param_default[UNDETAILED][i];
	  }
	  if(weighting_quant_param==2)
	  {
		  for(i=0;i<6;i++)
			  quant_param_detail[i]=(char)se_v("quant_param_delta_d")+wq_param_default[DETAILED][i];
	  }
	  //M2331 2008-04
    }
  }
#endif

  img->qp                = picture_qp;

#if !MULTIVIEW_CODING
  if ( picture_coding_type == 1 )
  {
	  img->type = P_IMG;
  }
#if DHP
  else if ( picture_coding_type == 3 )
  {
	  img->type = F_IMG;
  }
#endif
  else
  {
    img->type = B_IMG;
  }
#endif
}
/*
*************************************************************************
* Function:decode extension and user data
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void extension_data ( char *buf, int startcodepos, int length )
{
  int ext_ID;

  memcpy ( currStream->streamBuffer, buf, length );
  currStream->code_len = currStream->bitstream_length = length;
  currStream->read_len = currStream->frame_bitoffset = ( startcodepos + 1 ) * 8;

  ext_ID = u_v ( 4, "extension ID" );

  switch ( ext_ID )
  {
  case SEQUENCE_DISPLAY_EXTENSION_ID:
    sequence_display_extension();
    break;
  case COPYRIGHT_EXTENSION_ID:
    copyright_extension();
    break;
  case PICTURE_DISPLAY_EXTENSION_ID:
    picture_display_extension();
    break;    //rm52k_r1
  case CAMERAPARAMETERS_EXTENSION_ID:
    cameraparameters_extension();
    break;
#if M3480_TEMPORAL_SCALABLE
  case TEMPORAL_SCALABLE_EXTENSION_ID:
	  scalable_extension();
	break;
#endif
#if ROI_M3264  
  case LOCATION_DATA_EXTENSION_ID:
    input->ROI_Coding = 1;
    OpenPosFile( input->out_datafile );	
    roi_parameters_extension();
    break; 
#endif
  default:
    printf ( "reserved extension start code ID %d\n", ext_ID );
    break;
  }

}
/*
*************************************************************************
* Function: decode sequence display extension
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void sequence_display_extension()
{
  video_format      = u_v ( 3, "video format ID" );
  video_range       = u_v ( 1, "video range" );
  color_description = u_v ( 1, "color description" );

  if ( color_description )
  {
    color_primaries          = u_v ( 8, "color primaries" );
    transfer_characteristics = u_v ( 8, "transfer characteristics" );
    matrix_coefficients      = u_v ( 8, "matrix coefficients" );
  }

  display_horizontal_size = u_v ( 14, "display_horizontaol_size" );
  marker_bit              = u_v ( 1, "marker bit" );
  display_vertical_size   = u_v ( 14, "display_vertical_size" );
#if !M3472
  u_v ( 2, "reserved bits" );
#else
  TD_mode                = u_v ( 1, "3D_mode" );

  if ( TD_mode )
  {
    view_packing_mode         = u_v ( 8, "view_packing_mode" );
    view_reverse              = u_v ( 1, "view_reverse" );
  }
#endif

}

/*
*************************************************************************
* Function: decode picture display extension
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void picture_display_extension()
{
  int NumberOfFrameCentreOffsets;
  int i;

  if ( progressive_sequence == 1 )
  {
    if ( repeat_first_field == 1 )
    {
      if ( top_field_first == 1 )
      {
        NumberOfFrameCentreOffsets = 3;
      }
      else
      {
        NumberOfFrameCentreOffsets = 2;
      }
    }
    else
    {
      NumberOfFrameCentreOffsets = 1;
    }
  }
  else
  {
    if ( img->picture_structure == 1 )
    {
      if ( repeat_first_field == 1 )
      {
        NumberOfFrameCentreOffsets = 3;
      }
      else
      {
        NumberOfFrameCentreOffsets = 2;
      }
    }
  }

  for ( i = 0; i < NumberOfFrameCentreOffsets; i++ )
  {
    frame_centre_horizontal_offset[i] = u_v ( 16, "frame_centre_horizontal_offset" );
    marker_bit = u_v ( 1, "marker_bit" );
    frame_centre_vertical_offset[i]   = u_v ( 16, "frame_centre_vertical_offset" );
    marker_bit = u_v ( 1, "marker_bit" );
  }
}

/*
*************************************************************************
* Function:user data //sw
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void user_data ( char *buf, int startcodepos, int length )
{
  int i;
  int user_data;
  memcpy ( currStream->streamBuffer, buf, length );

  currStream->code_len = currStream->bitstream_length = length;
  currStream->read_len = currStream->frame_bitoffset = ( startcodepos + 1 ) * 8;

  for ( i = 0; i < length - 4; i++ )
  {
    user_data = u_v ( 8, "user data" );
  }
}

/*
*************************************************************************
* Function:Copyright extension //sw
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void copyright_extension()
{
  int reserved_data;
  int marker_bit;
  int copyright_number;

  copyright_flag       =  u_v ( 1, "copyright_flag" );
  copyright_identifier =  u_v ( 8, "copyright_identifier" );
  original_or_copy     =  u_v ( 1, "original_or_copy" );

  /* reserved */
  reserved_data        = u_v ( 7, "reserved_data" );
  marker_bit           = u_v ( 1, "marker_bit" );
  copyright_number_1 = u_v ( 20, "copyright_number_1" );
  marker_bit         = u_v ( 1, "marker_bit" );
  copyright_number_2 = u_v ( 22, "copyright_number_2" );
  marker_bit         = u_v ( 1, "marker_bit" );
  copyright_number_3 = u_v ( 22, "copyright_number_3" );

  copyright_number = ( copyright_number_1 << 44 ) + ( copyright_number_2 << 22 ) + copyright_number_3;

}


/*
*************************************************************************
* Function:camera parameters extension //sw
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void cameraparameters_extension()
{

  u_v ( 1, "reserved" );
  camera_id               = u_v ( 7, "camera id" );
  marker_bit = u_v ( 1, "marker bit" );
  height_of_image_device  = u_v ( 22, "height_of_image_device" );
  marker_bit = u_v ( 1, "marker bit" );
  focal_length            = u_v ( 22, "focal_length" );
  marker_bit = u_v ( 1, "marker bit" );
  f_number                = u_v ( 22, "f_number" );
  marker_bit = u_v ( 1, "marker bit" );
  vertical_angle_of_view  = u_v ( 22, "vertical_angle_of_view" );
  marker_bit = u_v ( 1, "marker bit" );

  camera_position_x_upper = u_v ( 16, "camera_position_x_upper" );
  marker_bit = u_v ( 1, "marker bit" );
  camera_position_x_lower = u_v ( 16, "camera_position_x_lower" );
  marker_bit = u_v ( 1, "marker bit" );

  camera_position_y_upper = u_v ( 16, "camera_position_y_upper" );
  marker_bit = u_v ( 1, "marker bit" );
  camera_position_y_lower = u_v ( 16, "camera_position_y_lower" );
  marker_bit = u_v ( 1, "marker bit" );

  camera_position_z_upper = u_v ( 16, "camera_position_z_upper" );
  marker_bit = u_v ( 1, "marker bit" );
  camera_position_z_lower = u_v ( 16, "camera_position_z_lower" );
  marker_bit = u_v ( 1, "marker bit" );

  camera_direction_x      = u_v ( 22, "camera_direction_x" );
  marker_bit = u_v ( 1, "marker bit" );

  camera_direction_y      = u_v ( 22, "camera_direction_y" );
  marker_bit = u_v ( 1, "marker bit" );

  camera_direction_z      = u_v ( 22, "camera_direction_z" );
  marker_bit = u_v ( 1, "marker bit" );

  image_plane_vertical_x  = u_v ( 22, "image_plane_vertical_x" );
  marker_bit = u_v ( 1, "marker bit" );

  image_plane_vertical_y  = u_v ( 22, "image_plane_vertical_y" );
  marker_bit = u_v ( 1, "marker bit" );

  image_plane_vertical_z  = u_v ( 22, "image_plane_vertical_z" );
  marker_bit = u_v ( 1, "marker bit" );

  u_v ( 32, "reserved data" );
}
#if M3480_TEMPORAL_SCALABLE
void scalable_extension()
{
	int i;
	int max_temporal_level = u_v ( 3, "max temporal level" );
	for( i = 0; i < max_temporal_level; i ++ )
	{
		u_v ( 4, "fps code per temporal level" );
		u_v ( 18, "bit rate lower" );
		u_v ( 1, "marker bit" );
		u_v ( 12, "bit rate upper" );
	}
}
#endif
/*
*************************************************************************
* Function:To calculate the poc values
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/

void calc_picture_distance ()
{
  // for POC mode 0:
  unsigned int        MaxPicDistanceLsb = ( 1 << 8 );

#if MULTIVIEW_CODING
  if ( img->coding_order  <  img->multiView_PrevPicDistanceLsb[img->view_index])
#else
  if ( img->coding_order  <  img->PrevPicDistanceLsb)
#endif
  {
#if REF_MINUS
	  {
		  int i, j;
#if MULTIVIEW_CODING
		  if (img->view_index == 0 && img->bDepth == 0)
		  {
			  total_frames++;
		  }
#else
		  total_frames++;
#endif
		  for (i=0; i<REF_MAXBUFFER; i++)
		  {
			  if (img->imgtr_fwRefDistance[i] >= 0)
			  {
				  img->imgtr_fwRefDistance[i] -= 256;
				  img->imgcoi_ref[i] -= 256;
			  }
			  for (j=0; j<4; j++)
			  {
				  ref_poc[i][j] -= 256;
			  }
		  }
#if MULTIVIEW_CODING
		  for (i=0; i<REF_MAXBUFFER; i++)
		  {
			  if (img->multiView_imgtr_fwRefDistance[img->view_index] >= 0)
			  {
				  img->multiView_imgtr_fwRefDistance[img->view_index][i] -= 256;
				  img->multiView_imgcoi_ref[img->view_index][i] -= 256;
			  }
			  if (img->multiView_depth_imgtr_fwRefDistance[img->view_index] >= 0)
			  {
				  img->multiView_depth_imgtr_fwRefDistance[img->view_index][i] -= 256;
				  img->multiView_depth_imgcoi_ref[img->view_index][i] -= 256;
			  }

			  for (j=0; j<4; j++)
			  {
				  multiView_ref_poc[img->view_index][i][j] -= 256;
				  multiView_depth_ref_poc[img->view_index][i][j] -= 256;
			  }
		  }
#endif
		  last_output -= 256;
#if MULTIVIEW_CODING
		  multiView_last_output[img->view_index] -= 256;
		  multiView_depth_last_output[img->view_index] -= 256;
		  for (i=0; i<outprint.buffer_num[img->view_index]; i++)
#else
		  for (i=0; i<outprint.buffer_num; i++)
#endif		 
		  {
#if MULTIVIEW_CODING
			  outprint.stdoutdata[img->view_index][i].framenum -= 256;
			  outprint.stdoutdata[img->view_index][i].tr -= 256;

			  outprint.depth_stdoutdata[img->view_index][i].framenum -= 256;
			  outprint.depth_stdoutdata[img->view_index][i].tr -= 256;
#else
			  outprint.stdoutdata[i].framenum -= 256;
			  outprint.stdoutdata[i].tr -= 256;
#endif
		  }
		  curr_IDRtr  -= 256;
		  curr_IDRcoi -= 256;
		  next_IDRtr  -= 256;
		  next_IDRcoi -= 256;
	  }
#else
	  img->CurrPicDistanceMsb += MaxPicDistanceLsb;
#endif
  }
#if !REF_MINUS
  img->coding_order += img->CurrPicDistanceMsb ;
#endif
#if PDD
  if (low_delay == 0)
  {
	  img->tr = img->coding_order + displaydelay -picture_reorder_delay;
  } 
  else
  {
	  img->tr = img->coding_order;
  }

#else
  img->tr = img->coding_order - delta_COI_POI;
#endif

  img->pic_distance = img->tr%256;
  picture_distance = img->pic_distance;

}

void SliceHeader ( char *buf, int startcodepos, int length )
{
  int mb_row;
  int mb_column;
  int mb_width;

  memcpy ( currStream->streamBuffer, buf, length );
  currStream->code_len = currStream->bitstream_length = length;

  currStream->read_len = currStream->frame_bitoffset = ( startcodepos ) * 8;
  slice_vertical_position              = u_v ( 8, "slice vertical position" );

  if ( vertical_size > (144*(1<<input->g_uiMaxSizeInBit)) )
  {
    slice_vertical_position_extension  = u_v ( 3, "slice vertical position extension" );
  }

  if ( vertical_size > (144*(1<<input->g_uiMaxSizeInBit)) )
  {
    mb_row = ( slice_vertical_position_extension << 7 ) + slice_vertical_position;
  }
  else
  {
    mb_row = slice_vertical_position;
  }

#if LCUBASE_SLICE
  slice_horizontal_positon = u_v ( 8, "slice horizontal position" );
  if ( img->width > (255*(1<<input->g_uiMaxSizeInBit)) )
  {
    slice_horizontal_positon_extension = u_v ( 2, "slice horizontal position extension" );
  }
#endif

  if ( input->profile_id == RESERVED_PROFILE_ID )
  {
    if ( input->slice_set_enable )
    {
      slice_horizontal_positon = u_v ( 8, "slice horizontal position" );

      if ( horizontal_size > 4080 )
      {
        slice_horizontal_positon_extension = u_v ( 2, "slice horizontal position extension" );
      }

      img->current_slice_set_index = u_v ( 6, "slice set index" );
      img->current_slice_header_flag = u_v ( 1, "slice header flag" );

      if ( horizontal_size > 4080 )
      {
        mb_column = ( slice_horizontal_positon_extension << 8 ) + slice_horizontal_positon;
      }
      else
      {
        mb_column = slice_horizontal_positon;
      }
    }
  }

#if M3198_CU8
  mb_width  = ( horizontal_size + MIN_CU_SIZE - 1) / MIN_CU_SIZE;
#else
  mb_width  = ( horizontal_size + 15 ) / 16;
#endif

  if ( !input->slice_set_enable || ( input->slice_set_enable && img->current_slice_header_flag ) ) //added by mz, 2008.04
  {
    if ( !fixed_picture_qp )
    {
      fixed_slice_qp   = u_v ( 1, "fixed_slice_qp" );
      slice_qp         = u_v ( 6, "slice_qp" );

      img->qp = slice_qp;
      img->slice_set_qp[img->current_slice_set_index] = slice_qp; //added by mz, 2008.04
#if MB_DQP
      input->useDQP = !fixed_slice_qp;
#endif
    }
#if MB_DQP
    else
    {
      input->useDQP = 0;
    }
#endif
  }
#if MB_DQP
  else {
    input->useDQP = 0;
  }
#endif

  //added by mz, 2008.04
  if ( input->slice_set_enable && !img->current_slice_header_flag )
  {
    img->qp = img->slice_set_qp[img->current_slice_set_index];
  }
  if (input->sao_enable)
  {
	  img->slice_sao_on[0] = u_v ( 1, "sao_slice_flag_Y" );
	  img->slice_sao_on[1] = u_v ( 1, "sao_slice_flag_Cb" );
	  img->slice_sao_on[2] = u_v ( 1, "sao_slice_flag_Cr" );
  }
}

/*
*************************************************************************
* Function:Error handling procedure. Print error message to stderr and exit
with supplied code.
* Input:text
Error message
* Output:
* Return:
* Attention:
*************************************************************************
*/

void error ( char *text, int code )
{
  fprintf ( stderr, "%s\n", text );
  exit ( code );
}

//Lou
int sign ( int a , int b )
{
  int x;

  x = abs ( a );

  if ( b > 0 )
  {
    return ( x );
  }
  else
  {
    return ( -x );
  }
}
